#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include "seg.h"
#include "kw.h"
#include "utils.h"
#include "lexer.h"
#include "lexer.h"
#include "vty.h"

static char progname[PROMPT_MAX] = "";
static long vty_options = 0;
 
void vty_init(long options)
{
  vty_options = 0;
  set_vty_options(options);
}

void vty_exit(void)
{
	unset_vty_options(vty_options);
}

void set_vty_options(long options)
{
	if (options & VTY_OPT_CBREAK) {
		int ret UNUSED = system("stty -echo cbreak >/dev/null 2>&1");
	}
	if ((options & VTY_OPT_PROMPT) && !(vty_options & VTY_OPT_PROMPT)){
		vty_options |= VTY_OPT_PROMPT;
		show_vty_prompt();
	}
	vty_options |= options;
}

void unset_vty_options(long options)
{
	if (options & VTY_OPT_CBREAK) {
		int ret UNUSED = system("stty echo cbreak >/dev/null 2>&1");
	}
	vty_options &= (~options);
}

void set_progname(const char *n)
{
  if (n == NULL || n[0] == 0)
    n = "bolt";
  const char *ptr = n;
	for (; n[0] != 0; n++) {
		if (n[0] == '/')
			ptr=n+1;
	}
  int ret = snprintf(progname, PROMPT_MAX - 1, "%s", ptr);
  progname[ret] = 0;
}

void show_vty_prompt(void)
{
	if (vty_options & VTY_OPT_PROMPT) {
		int ret UNUSED;
		ret = write(STDOUT_FILENO, progname, strlen(progname));
		ret = write(STDOUT_FILENO, "#", 1);
	}
}

void vty_newline(void)
{
	struct lexer lex;
	const char *buf;
  printf("\n");
  int buf_size  = get_linebuf(&buf);
  init_lexer(&lex, buf, make_seg(0, buf_size));
	lexer_execute(&lex);
	init_linebuf();
	show_vty_prompt();
}

void vty_backspace(void)
{
	if (backspace_linebuf()) {
    printf("\b \b");
    fflush(stdout);
  }
}

static void vty_autofill(struct lexer *lex)
{
	const char *buf = lexer_get_autofill(lex);
	add_linebuf(buf, strlen(buf));
	lexer_reset_autofill(lex);
}

void vty_table(void)
{
	struct lexer lex;
  const char *buf;
  printf ("\n");
  fflush(stdout);
  int buf_size = get_linebuf(&buf);
	init_lexer(&lex, buf, make_seg(0, buf_size));
	lexer_help(&lex);
	vty_autofill(&lex);
	fflush(stdout);
	show_vty_prompt();
  buf_size = get_linebuf(&buf);
  printf("%s", buf);
  fflush(stdout);
}

void vty_trigger(char trigger)
{
	switch (trigger) {
	case TRIGGER_NEWLINE:
	case TRIGGER_COMMA:
		vty_newline();
		break;
	case TRIGGER_BACKSPACE1:
	case TRIGGER_BACKSPACE2:
		vty_backspace();
		break;
	case TRIGGER_TABLE:
		vty_table();
		break;
	}
}

int vty_read(const char *buf, int size)
{
  const char *trigger = TRIGGER_SET;
  while (size > 0) {
    const char *first = buf + size;
    for (trigger = TRIGGER_SET; trigger[0] != 0; trigger++) {
      char *ptr = strchr(buf, trigger[0]);
      if (ptr != NULL && ptr < first)
        first = ptr;
    }
    if (first > buf && add_linebuf(buf, first - buf) > 0) {
      int i;
      for (i = 0; i < first - buf; i++){
        printf("%c", buf[i]);
      }
      fflush(stdout);
    }
    if (first[0] != 0) {
      vty_trigger(first[0]);
      first++;
    }
    size -= (first - buf);
    buf = first;
  }
  return 0;
}





